package cn.you.GenghisKhan.common.zip;

import cn.you.GenghisKhan.common.dataset.DataType;
import cn.you.GenghisKhan.common.dataset.Record;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;


public class Zip {
    public static final byte zipVersion = 1;// /暂时是第1 个版本 开始版本 如果 以后有更改压缩算是更改版本
    // 默认压缩版本

    /**
     * 对字节数组进行压缩WFP系统使用
     *
     * @throws IOException
     *
     * */
    public static byte[] compress(byte[] noBytes) throws IOException {
        if (noBytes == null)
            return null;
        byte[] zipBytes = gZipBytes(noBytes);
        // /1.把压缩过的数组经过WFP 的Reade 转换为 和C# 通用的字节数组
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        stream.write(zipVersion);// 写入压缩版本号 为以后的压缩算法更改做扩展准备
        Record.WriteTypeValue(stream, DataType.Bytes, zipBytes);
        return stream.toByteArray();
    }

    public static byte[] compress(byte[] noBytes, byte zipVer) throws IOException {
        if (noBytes == null)
            return null;
        byte[] zipBytes = gZipBytes(noBytes);
        // /1.把压缩过的数组经过WFP 的Reade 转换为 和C# 通用的字节数组
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        stream.write(zipVer);// 写入压缩版本号 为以后的压缩算法更改做扩展准备
        Record.WriteTypeValue(stream, DataType.Bytes, zipBytes);
        return stream.toByteArray();
    }

    public static byte[] uncompress(byte[] zipBytes) throws IOException {
        if (zipBytes == null)
            return null;
        ByteArrayInputStream stream = new ByteArrayInputStream(zipBytes);
        byte zipVer = (byte) stream.read();
        byte[] zipbytes = (byte[]) Record.ReadTypeValue(stream, DataType.Bytes);
        if (zipVersion == zipVer) {
            return unGZipBytes(zipbytes);
        }
        return null;
    }

    /**
     * 对字节数组进行解压缩 WFP系统使用
     *
     * @throws IOException
     *
     * */
    public static byte[] uncompress(byte[] zipBytes, byte zipVer) throws IOException {
        if (zipBytes == null)
            return null;
        ByteArrayInputStream stream = new ByteArrayInputStream(zipBytes);
        if (zipVersion == zipVer) {
            return unGZipBytes(zipBytes);
        }
        return null;
    }

    /***
     * 压缩GZip
     *
     * @param data
     * @return
     */
    public static byte[] gZip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(bos);
            gzip.write(data);
            gzip.finish();
            gzip.close();
            b = bos.toByteArray();
            bos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 解压GZip
     *
     * @param data
     * @return
     */
    public static byte[] unGZip(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            GZIPInputStream gzip = new GZIPInputStream(bis);
            byte[] buf = new byte[1024];
            int num = -1;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((num = gzip.read(buf, 0, buf.length)) != -1) {
                baos.write(buf, 0, num);
            }
            b = baos.toByteArray();
            baos.flush();
            baos.close();
            gzip.close();
            bis.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 压缩Zip
     *
     * @param data
     * @return
     */
    public static byte[] zipBytes(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ZipOutputStream zip = new ZipOutputStream(bos);
            ZipEntry entry = new ZipEntry("zip");
            entry.setSize(data.length);
            zip.putNextEntry(entry);
            zip.write(data);
            zip.closeEntry();
            zip.close();
            b = bos.toByteArray();
            bos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /***
     * 解压Zip
     *
     * @param data
     * @return
     */
    public static byte[] unZipBytes(byte[] data) {
        byte[] b = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            ZipInputStream zip = new ZipInputStream(bis);
            while (zip.getNextEntry() != null) {
                byte[] buf = new byte[1024];
                int num = -1;
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                while ((num = zip.read(buf, 0, buf.length)) != -1) {
                    baos.write(buf, 0, num);
                }
                b = baos.toByteArray();
                baos.flush();
                baos.close();
            }
            zip.close();
            bis.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return b;
    }

    /**
     * 函数说明:GZip压缩字节数组
     * */
    public static byte[] gZipBytes(byte[] noZipBytes) throws IOException {
        if (noZipBytes == null)
            return null;
        byte[] tArray;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        try {
            gzip.write(noZipBytes);
            gzip.flush();
        } finally {
            gzip.close();
        }
        tArray = out.toByteArray();
        out.close();
        return tArray;
    }

    /**
     * 函数说明:GZip解压字节数组
     *
     * */
    public static byte[] unGZipBytes(byte[] zipBytes) throws IOException {
        if (zipBytes == null)
            return null;

        // BASE64Decoder tBase64Decoder = new BASE64Decoder();
        // byte[] t = tBase64Decoder.decodeBuffer(str);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(zipBytes);
        GZIPInputStream gunzip = new GZIPInputStream(in);
        try {
            byte[] buffer = new byte[256];
            int n;
            while ((n = gunzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
        } finally {
            gunzip.close();
        }
        in.close();
        out.close();
        return out.toByteArray();
    }
}